package ldh.im.fxgui.handle;

import javafx.concurrent.Task;
import javafx.scene.layout.StackPane;
import ldh.im.ImConfig;
import ldh.im.dto.base.OkListResp;
import ldh.im.dto.business.base.CollectCreateReq;
import ldh.im.dto.business.item.CollectInfoItem;
import ldh.im.exception.ImServiceException;
import ldh.im.fxbase.dao.ImCollectDao;
import ldh.im.fxbase.dao.ImSessionDao;
import ldh.im.fxbase.data.pojo.ImCollect;
import ldh.im.fxbase.data.pojo.ImMessage;
import ldh.im.fxbase.data.pojo.ImSession;
import ldh.im.fxbase.data.pojo.status.ImCollectContent;
import ldh.im.fxbase.exception.ImErrorCode;
import ldh.im.fxbase.rpc.service.RpcBaseService;
import ldh.im.fxbase.service.CollectService;
import ldh.im.fxbase.service.ImSessionService;
import ldh.im.fxbase.util.*;
import ldh.im.fxgui.util.UiUtil;
import ldh.rpc.util.JsonUtil;
import ldh.rpc.exception.RpcException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class CollectHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(CollectHandler.class);

    private ImCollectDao imCollectDao = BeanFactory.getInstance().getBean(ImCollectDao.class);
    private ImSessionDao imSessionDao = BeanFactory.getInstance().getBean(ImSessionDao.class);

    private CollectService collectService = BeanFactory.getInstance().getBean(CollectService.class);

    public void collectMessage(StackPane dialogRoot, ImMessage imMessage) {
        collectMessages(dialogRoot, Arrays.asList(imMessage));
    }

    public Task collectMessages(StackPane dialogRoot, List<ImMessage> imMessages) {
        Task task = new Task() {

            @Override
            protected Object call() throws Exception {
                String userId = UiUtil.getLoginImUser().getUserId();

                List<ImCollect> collectList = new ArrayList<>(imMessages.size());
                for (ImMessage imMessage : imMessages) {
                    if (imMessage.getSessionId() == null) {
                        ImSessionService imSessionService = BeanFactory.getInstance().getBean(ImSessionService.class);
                        ImSessionDao imSessionDao = BeanFactory.getInstance().getBean(ImSessionDao.class);
                        ImSession imSession = imSessionService.pullSession(imMessage.getFromUserId(), imMessage.getToUserId(), imMessage.getGroupCode());
                        imSessionDao.updateServerId(imSession);
                    }

                    ImSession imSession = imMessage.getImSession();
                    if (imSession == null) {
                        imSession = imSessionDao.getSessionById(imMessage.getSessionId());
                        imMessage.setImSession(imSession);
                    }

                    ImCollect dbCollect = imCollectDao.getByKey(userId, imSession.getServerId(), imMessage.getServerId());
                    if (dbCollect != null) {
                        throw new ImServiceException(ImErrorCode.Collect_existed);
                    }

                    ImCollect collect = new ImCollect();
                    ImCollectContent collectContent = new ImCollectContent(imMessage);
                    collect.setContent(JsonUtil.toJson(collectContent));
                    collect.setMessageType(imMessage.getMessageType());
                    collect.setMessageId(imMessage.getServerId());
                    collect.setUserId(UiUtil.getLoginImUser().getUserId());
                    collect.setSessionId(imMessage.getImSession().getServerId());

                    collectList.add(collect);
                }

                List<CollectInfoItem> collectItems = collectList.stream().map(collect->{
                    CollectInfoItem collectItem = new CollectInfoItem();
                    collectItem.setMessageType(collect.getMessageType());
                    collectItem.setContent(collect.getContent());
                    collectItem.setLabelIds(collect.getLabelIds());
                    collectItem.setSessionId(collect.getSessionId());
                    collectItem.setMessageId(collect.getMessageId());
                    return collectItem;
                }).collect(Collectors.toList());

                RpcBaseService rpcBaseService = RpcUtil.getRpcBootstrap().getRpcConfig().getClientBean(RpcBaseService.class);
                CollectCreateReq collectCreateReq = new CollectCreateReq();
                collectCreateReq.setCollectInfoItems(collectItems);

                OkListResp okListResp = rpcBaseService.createCollect(collectCreateReq);
                Set<String> keySet = okListResp.getLocalSeqSet();

                Map<String, ImMessage> messageMap = imMessages.stream().collect(Collectors.toMap(ImMessage::getServerId, Function.identity()));
                Map<String, ImCollect> collectMap = collectList.stream().collect(Collectors.toMap(ImCollect::getMessageId, Function.identity()));
                for (String keys : keySet) {
                    String[] ids = keys.split(ImConfig.MESSAGE_SPLIT);
                    String messageId = ids[0];
                    String serverId = ids[1];
                    ImMessage imMessage = messageMap.get(messageId);
                    ImCollect collect = collectMap.get(messageId);
                    collect.setServerId(serverId);

                    collectService.collectMoveMessageAttachFile(userId, imMessage);  // 迁移消息中的文件

                    ImCollectContent collectContent = new ImCollectContent(imMessage);
                    collect.setContent(JsonUtil.toJson(collectContent));
                    imCollectDao.insert(collect);
                }
                return null;
            }
        };
        ThreadPoolUtil.submitTask(task, "收藏消息");
        task.setOnSucceeded(s->{
            DialogUtil.showSuccess(dialogRoot, "收藏成功");
        });
        task.setOnFailed(e->{
            LOGGER.error("收藏失败", task.getException());
            if (task.getException() instanceof ImServiceException) {
                ImServiceException serviceException = (ImServiceException) task.getException();
                DialogUtil.showError(dialogRoot, serviceException.getMessage());
            } else if (task.getException() instanceof RpcException) {
                RpcException rpcException = (RpcException) task.getException();
                DialogUtil.showError(dialogRoot, rpcException.getMessage());
            } else {
                DialogUtil.showError(dialogRoot, "收藏失败");
            }
        });
        return task;
    }
}
